package com.butterfly.hotkey.starter.config;

import com.butterfly.hotkey.client.core.HotkeyStore;
import com.butterfly.hotkey.client.core.collector.DefaultKeyAccessCollector;
import com.butterfly.hotkey.client.core.collector.DefaultKeySummaryCollector;
import com.butterfly.hotkey.client.core.collector.IKeyCollector;
import com.butterfly.hotkey.client.core.config.AppClientProperties;
import com.butterfly.hotkey.client.core.service.HotkeyCacheService;
import com.butterfly.hotkey.client.core.service.KeyCollectorService;
import com.butterfly.hotkey.client.core.service.PushScheduleService;
import com.butterfly.hotkey.client.core.service.WorkerService;
import com.butterfly.hotkey.core.constant.Constants;
import com.butterfly.hotkey.core.model.HotKeyModel;
import com.butterfly.hotkey.core.model.KeyCountModel;
import com.butterfly.hotkey.core.model.KeyModel;
import com.butterfly.hotkey.starter.properties.HotkeyClientProperties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.lang.NonNull;

import java.util.Optional;

/**
 * Client 容器配置
 * 1. 初始化配置中心信息，从配置中心拉取当前app配置信息
 * 2. 初始化worker信息，从config-center拉取所有的channel，并进行初始化
 * 3. 初始化配置信息，比如缓存大小配置，推送间隔
 *
 * @author butterfly
 * @since 2024/10/19
 */
@ConditionalOnProperty(prefix = Constants.HOTKEY, name = "enabled", matchIfMissing = true)
@EnableConfigurationProperties(HotkeyClientProperties.class)
public class HotkeyClientAutoConfiguration implements ApplicationContextAware {

    private ConfigurableApplicationContext applicationContext;

    @Bean
    public AppClientProperties clientProperties(HotkeyClientProperties hotkeyClientProperties) {
        String applicationName = applicationContext.getApplicationName();

        AppClientProperties clientProperties = new AppClientProperties();
        clientProperties.setWorkerUrls(hotkeyClientProperties.getWorkerUrls());
        clientProperties.setClientKeyRules(hotkeyClientProperties.getClientKeyRules());
        clientProperties.setAppName(Optional.ofNullable(hotkeyClientProperties.getAppName()).orElse(applicationName));
        clientProperties.setPushKeyIntervalMillis(hotkeyClientProperties.getPushKeyIntervalMillis());
        clientProperties.setPushSummarySecs(hotkeyClientProperties.getPushSummarySecs());
        clientProperties.setWarmSecs(hotkeyClientProperties.getWarmSecs());
        clientProperties.setCache(hotkeyClientProperties.getCache());
        clientProperties.setReConnectWorkerIntervalMillis(hotkeyClientProperties.getReConnectWorkerIntervalMillis());
        clientProperties.setFetchClientConfigSecs(hotkeyClientProperties.getFetchClientConfigSecs());
        clientProperties.setFetchWorkerPathSecs(hotkeyClientProperties.getFetchWorkerPathSecs());

        return clientProperties;
    }

    @Bean
    public HotkeyStore hotkeyStore(AppClientProperties clientProperties,
                                   KeyCollectorService keyCollectorService,
                                   HotkeyCacheService cacheService) {
        return new HotkeyStore(clientProperties, keyCollectorService, cacheService);
    }

    @Bean
    public HotkeyCacheService hotkeyCacheService(AppClientProperties clientProperties) {
        return new HotkeyCacheService(clientProperties);
    }

    @Bean
    public WorkerService workerService(AppClientProperties clientProperties, HotkeyStore hotkeyStore) {
        return new WorkerService(clientProperties, hotkeyStore);
    }

    @Bean
    public KeyCollectorService keyCollector(@Qualifier("keySummaryCollector") IKeyCollector<KeyModel, KeyCountModel> keySummaryCollector,
                                            @Qualifier("keyAccessCollector") IKeyCollector<HotKeyModel, HotKeyModel> keyAccessCollector) {
        return new KeyCollectorService(keySummaryCollector, keyAccessCollector);
    }

    @Bean
    public PushScheduleService pushScheduleService(WorkerService workerService, AppClientProperties clientProperties, KeyCollectorService keyCollectorService) {
        return new PushScheduleService(keyCollectorService, workerService, clientProperties);
    }

    @Bean("keySummaryCollector")
    @ConditionalOnMissingBean(name = "keySummaryCollector")
    public IKeyCollector<KeyModel, KeyCountModel> keySummaryCollector(AppClientProperties clientProperties) {
        return new DefaultKeySummaryCollector(clientProperties);
    }

    @Bean("keyAccessCollector")
    @ConditionalOnMissingBean(name = "keyAccessCollector")
    public IKeyCollector<HotKeyModel, HotKeyModel> keyAccessCollector() {
        return new DefaultKeyAccessCollector();
    }

    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = (ConfigurableApplicationContext) applicationContext;
    }
}
